package com.fj.order.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.fj.domain.Order;
import com.fj.domain.Product;
import com.fj.domain.User;
import com.fj.order.dao.OrderDao;
import com.fj.order.feign.ProductService;
import com.fj.order.feign.UserService;
import com.fj.order.service.OrderService;
import com.fj.order.web.dto.FjResponse;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author fj
 * @date 2024/3/12 00:29
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Resource
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Override
    public Order order(Order order) {
        return orderDao.save(order);
    }

    private int count;
    @Override
    @SentinelResource(value = "service", blockHandler = "blockHandler", fallback = "fallback")
    public FjResponse<Object> getOrder(Integer oid) {
        if (++count%3==0){
            throw new RuntimeException("模拟异常");
        }
        Order order = orderDao.getById(oid);
        return FjResponse.ok(order);
    }

    @GlobalTransactional(name = "createOrder") //seata必须
    @Override
    public Order createOrder(Integer uid, Integer pid, Integer number) {
        User user = userService.getUser(uid);
        Order order = new Order();
        order.setUid(uid);
        order.setUsername(user.getUsername());
        order.setPid(pid);
        Product product = productService.getProduct(pid);
        order.setPname(product.getPname());
        order.setNumber(number);
        BigDecimal orderPrice = BigDecimal.valueOf(product.getPprice()).multiply(BigDecimal.valueOf(number));
        order.setPprice(orderPrice.setScale(2, RoundingMode.HALF_UP).toPlainString());
        Order save = orderDao.save(order);
        log.info("订单保存成功|{}",save);
        int money = orderPrice.multiply(BigDecimal.TEN.multiply(BigDecimal.TEN)).intValue();
        User user1 = userService.reduceMoney(uid, money);
        log.info("用户余额扣减成功|{}",user1);
        Product product1 = productService.reduceStock(pid, number);
        log.info("商品库存扣减成功|{}",product1);
        return save;
    }

    private FjResponse<Object> blockHandler(Integer oid, BlockException e){
        log.error("限流异常",e);
        return FjResponse.fail("sentinel限流");
    }

    private FjResponse<Object> fallback(Integer oid, Throwable throwable){
        log.error("其它异常",throwable);
        return FjResponse.fail("其它异常");
    }
}
